import { TCatalogData, TProductData, TProductReview } from '../store/types'
import { config } from './config'

type TConfigApi = {
	baseUrl: string
	token: string
}

export type TUser = {
	name: string
	about: string
	avatar: string
	email: string
	password: string
	isAdmin: boolean
	group: string
	_id: string
}

export type TAllProductsResponse = {
	total: number
	products: TCatalogData[]
}

export type TCatalogRequest = {
	page: number
	limit: number
	search?: string
}

export type TCatalogResponse = {
	total: number
	products: TCatalogData[]
}

export type TProductRequest = {
	id: string
}

export type TProductResponse = TProductData

export type TEditUserRequest = {
	name: string
	about: string
}

export type TProductReviewRequest = {
	productId: TProductData['_id']
	review: {
		rating: TProductReview['rating']
		text: TProductReview['text']
	}
}

export type TProductReviewResponse = TProductData

export class Api {
	private baseUrl
	private headers: HeadersInit

	constructor({ baseUrl, token }: TConfigApi) {
		this.baseUrl = baseUrl
		this.headers = {
			'content-type': 'application/json',
			authorization: `Bearer ${token}`,
		}
	}

	private onResponse(res: Response) {
		return res.ok ? res.json() : res.json().then((err) => Promise.reject(err))
	}

	private getApiUrl(path: string) {
		return `${this.baseUrl}${path}`
	}

	async editUser(params: TEditUserRequest) {
		const res = await fetch(this.getApiUrl('/users/me'), {
			method: 'PATCH',
			headers: this.headers,
			body: JSON.stringify(params),
		})
		return this.onResponse(res)
	}

	async getAllProducts() {
		const res = await fetch(this.getApiUrl('/products'), {
			method: 'GET',
			headers: this.headers,
		})
		return this.onResponse(res)
	}

	async getProducts({ page, limit, search }: TCatalogRequest) {
		const res = await fetch(
			this.getApiUrl(
				`/products/?page=${page}&limit=${limit}` +
					`${search ? `&query=${search}` : ''}`
			),
			{
				method: 'GET',
				headers: this.headers,
			}
		)
		return this.onResponse(res)
	}

	async getProduct({ id }: TProductRequest) {
		const res = await fetch(this.getApiUrl(`/products/${id}`), {
			method: 'GET',
			headers: this.headers,
		})
		return this.onResponse(res)
	}

	async deleteProduct({ id }: TProductRequest) {
		const res = await fetch(this.getApiUrl(`/products/${id}`), {
			method: 'DELETE',
			headers: this.headers,
		})
		return this.onResponse(res)
	}

	async setLike({ id }: TProductRequest) {
		const res = await fetch(this.getApiUrl(`/products/likes/${id}`), {
			method: 'PUT',
			headers: this.headers,
		})
		return this.onResponse(res)
	}

	async setDislike({ id }: TProductRequest) {
		const res = await fetch(this.getApiUrl(`/products/likes/${id}`), {
			method: 'DELETE',
			headers: this.headers,
		})
		return this.onResponse(res)
	}

	async addProductReview(params: TProductReviewRequest) {
		const res = await fetch(
			this.getApiUrl(`/products/review/${params.productId}`),
			{
				method: 'POST',
				headers: this.headers,
				body: JSON.stringify(params.review),
			}
		)
		return this.onResponse(res)
	}
}

const api = (token: string) =>
	new Api({
		baseUrl: config.apiUrl,
		token: token,
	})

export default api
